package middleware

import (
	"crypto/sha256"
	"encoding/base64"
	"encoding/hex"
	"errors"
	"gitee.com/baal1990/epidemic/global"
	"github.com/gin-gonic/gin"
	"strings"
)

import (
	response "gitee.com/baal1990/epidemic/model/common/response_dfitc"
)

// XWsse x-wsse 校验
// Authorization=`WSSE profile="UsernameToken"`
// X-WSSE: UsernameToken Username="bob", PasswordDigest="quR/EWLAV4xLf9Zqyw4pDmfV9OY=", Nonce="d36e316282959a9ed4c89851497a717f", Created="2006-01-02T15:04:05Z"
// PasswordDigest=base64(sh256(Nonce + Created + AppSecret))
// Nonce 随机数
// Created 时间， 2006-01-02T15:04:05Z
func XWsse() gin.HandlerFunc {
	return func(c *gin.Context) {
		authorization := c.GetHeader("Authorization")
		xwsse := c.GetHeader("X-WSSE")
		// 校验Authorization，固定值
		if authorization != `WSSE profile="UsernameToken"` {
			response.FailWithDetailed(gin.H{"reload": true}, "未登录或非法访问", c)
			global.GVA_LOG.Sugar().Error("未登录或非法访问, Authorization=", authorization)
			c.Abort()
			return
		}
		// 校验X-WSSE
		xwsseMap := unmarshalXWSSE(xwsse)
		passwordDigest := xwsseMap["PasswordDigest"]
		appKey := xwsseMap["Username"]
		nonce := xwsseMap["Nonce"]
		created := xwsseMap["Created"]
		if err := checkPasswordDigest(appKey, nonce, created, passwordDigest); err != nil {
			response.FailWithDetailed(gin.H{"reload": true}, "未登录或非法访问", c)
			global.GVA_LOG.Sugar().Error("未登录或非法访问, err=", err)
			c.Abort()
			return
		}
		c.Next()
	}
}

// 反序列化X-WSSE
func unmarshalXWSSE(xwsse string) (result map[string]string) {
	result = make(map[string]string)
	xwsse = strings.Replace(xwsse, " ", "", -1)
	xwsse = strings.Replace(xwsse, "UsernameToken", "", -1)
	xwsse = strings.Replace(xwsse, `"`, "", -1)
	paras := strings.Split(xwsse, ",")
	for i := 0; i < len(paras); i++ {
		keyValue := strings.Split(paras[i], "=")
		if len(keyValue) == 2 {
			result[keyValue[0]] = keyValue[1]
		} else if len(keyValue) > 2 {
			// base64后面有=的情况
			result[keyValue[0]] = keyValue[1]
			for i := 0; i < len(keyValue)-2; i++ {
				result[keyValue[0]] += "="
			}
		}
	}
	return
}

// 获取appSecret
func getAppSecret(appKey string) (appSecret string, err error) {
	err = global.GVA_DB.Table("epidemic_interface_auth").Select("app_secret").
		Where("app_key=?", appKey).
		Find(&appSecret).Error
	return
}

// 校验PasswordDigest
// 只接受30s内请求，并且如果created比当前时间晚，也拒绝请求
func checkPasswordDigest(appKey, nonce, created, passwordDigest string) (err error) {
	//var createdTime time.Time
	//createdTime, err = time.Parse("2006-01-02T15:04:05Z", created)
	//if err != nil {
	//	return
	//}
	//now := time.Now()
	// created比当前时间靠后或者是30秒之前的请求，直接拒绝
	//if createdTime.After(now) || now.Sub(createdTime) > time.Second*30 {
	//	global.GVA_LOG.Sugar().Error("非法created：", created)
	//	return errors.New("非法X-WSSE")
	//}
	var appSecret string
	if appSecret, err = getAppSecret(appKey); err != nil {
		return
	}
	want := genPasswordDigest(nonce, created, appSecret)
	dataByte, err := base64.URLEncoding.DecodeString(passwordDigest)
	if err != nil {
		return
	}
	digest := string(dataByte)
	if want != digest {
		global.GVA_LOG.Sugar().Error("非法passwordDigest：", passwordDigest)
		return errors.New("非法X-WSSE")
	}
	return err
}

// 生成PasswordDigest
// PasswordDigest=base64(sh256(Nonce + Created + AppSecret))
func genPasswordDigest(nonce, created, appSecret string) string {
	tmp := sha256.Sum256([]byte(nonce + created + appSecret))
	passwordDigest := tmp[:]
	return hex.EncodeToString(passwordDigest)
}
